// /////////////////////////////////////////////////////////////////////////////
//
// Name:            EventsContainer.java
// Author:          Michael Bartsch
//
// Desc :           Defines the EventsContainer class.
//
// License:         Copyright (C) 2009 Michael Bartsch
//
//                  This software is provided 'as-is', without any express or
//                  implied warranty. In no event will the authors be held
//                  liable for any damages arising from the use of this
//                  software.
//
//                  Permission is granted to anyone to use this software for
//                  any purpose, including commercial applications, and to
//                  alter it and redistribute it freely, subject to the
//                  following restrictions:
//
//                  1. The origin of this software must not be misrepresented;
//                  you must not claim that you wrote the original software. If
//                  you use this software in a product, an acknowledgment in the
//                  product documentation would be appreciated but is not
//                  required.
//
//                  2. Altered source versions must be plainly marked as such,
//                  and must not be misrepresented as being the original
//                  software.
//
//                  3. This notice may not be removed or altered from any source
//                  distribution.
//
// /////////////////////////////////////////////////////////////////////////////

// Package
package net.dotsimplicity.events;

// Import classes
import java.util.LinkedList;


// EventsContainer class
/**
 * The EventsContainer is a collection of {@link Event Events}. The EventsContainer class provides
 * various tools for managing this collection.
 */
public class EventsContainer implements IEventsContainer
{
    // Public methods
	/**
	 * Constructs an EventsContainer with the given name.
	 * @param name           Name of the EventsContainer
	 */
	public EventsContainer(String name)
	{
	   this.name = name;
		
	   this.events = new LinkedList<Event>();
	}
	
	public void addEvent(Event event)
	{
	   // Check if the given event does not exist.
	   if(this.getEvent(event.getName()) != null)
		 throw new RuntimeException("EventContainer(" + this.name + ").addEvent: Event already exists\n");
		
	   // Add the event to our list.
	   this.events.add(event);
	}
	
	public void addEvents(Event [] events)
	{
	   for(Event event : events)
         this.addEvent(event);
	}
	
	public void connectEventSlot(String eventName, Object object, String methodName)
	{
	   // Retrieve reference to the requested event.
	   Event event = this.getEvent(eventName);
		   
	   if(event == null)
		 throw new RuntimeException("EventContainer(" + this.name + ").connectEventSignal: Event does not exist\n");
	   
	   // Connect the event slot.
	   event.connectEventSlot(object, methodName);
	}
	
	public void connectEventSlot(String eventName, Class<?> classReference, String methodName)
	{
	   // Retrieve reference to the requested event.
	   Event event = this.getEvent(eventName);
		   
	   if(event == null)
		 throw new RuntimeException("EventContainer(" + this.name + ").connectEventSignal: Event does not exist\n");
	   
	   // Connect the event slot.
	   event.connectEventSlot(classReference, methodName);
	}
	
	public Event createEvent(String eventName)
	{
	   return this.createEvent(eventName, (Class<?>[])null);
	}
	
	public Event createEvent(String eventName, Class<?> parameter)
	{
	   Class<?> [] parameters = { parameter };
	   return this.createEvent(eventName, parameters);
	}
	
	public Event createEvent(String eventName, Class<?> [] parameters)
	{
	   // Create a new event object and try to add it to the list.
	   Event event = new Event(eventName, parameters);
       this.addEvent(event);
	   
	   // Return the new event.
	   return event;
	}
	
	public Event [] createEvents(String [] eventNames)
	{
	   return this.createEvents(eventNames, (Class<?>[])null);
	}
	
	public Event [] createEvents(String [] eventNames, Class<?> parameter)
	{
	   Class<?> [] parameters = { parameter };
	   return this.createEvents(eventNames, parameters);
	}
	
	public Event [] createEvents(String [] eventNames, Class<?> [] parameters)
	{
	   // Create an array to hold the created events.
	   Event [] events = new Event[eventNames.length];
	   
	   // Create the events.
	   for(int i = 0; i < eventNames.length; i++)
		 events[i] = this.createEvent(eventNames[i], parameters);
	   
	   // Return the created events.
	   return events;
	}
	
	public void disconnectEventSlot(String eventName, Object object, String methodName)
	{
	   // Retrieve reference to the requested event.
	   Event event = this.getEvent(eventName);
		   
	   if(event == null)
		 throw new RuntimeException("EventContainer(" + this.name + ").connectEventSignal: Event does not exist\n");
	   
	   // Disconnect the event slot.
	   event.disconnectEventSlot(object, methodName);
	}
	
	public void disconnectEventSlot(String eventName, Class<?> classReference, String methodName)
	{
	   // Retrieve reference to the requested event.
	   Event event = this.getEvent(eventName);
		   
	   if(event == null)
		 throw new RuntimeException("EventContainer(" + this.name + ").connectEventSignal: Event does not exist\n");
	   
	   // Disconnect the event slot.
	   event.disconnectEventSlot(classReference, methodName);
	}
	
	public void emitEventSignal(String eventName)
	{
	   this.emitEventSignal(eventName, null);
	}
	
	public void emitEventSignal(String eventName, Object argument)
	{
	   Object [] arguments = { argument };
	   this.emitEventSignal(eventName, arguments);
	}
	
	public void emitEventSignal(String eventName, Object [] arguments)
	{
	   // Retrieve reference to the requested event.
	   Event event = this.getEvent(eventName);
	   
	   if(event == null)
		 throw new RuntimeException("EventContainer(" + this.name + ").emitEventSignal: Event does not exist\n");
	   
	   // Emit the signal.
	   event.emitEventSignal(arguments);
	}
	
	public Event getEvent(String eventName)
	{
	   // Try to retrieve the requested event.
	   for(Event event : this.events)
	   {
	      if(event.getName().equals(eventName))
	    	return event;
	   }
		
	   // We didn't find the event.
	   return null;
	}
	
	public void removeAllEvents()
	{
	   while(!this.events.isEmpty())
	     this.events.removeLast();
	}
	
	public void removeEvent(Event event)
	{
	   for(Event e : this.events)
	   {
	      if(e.equals(event))
	    	this.events.remove(e);
	   }
	}
	
	public void removeEvent(String eventName)
	{
	   for(Event event : this.events)
	   {
	      if(event.getName().equals(eventName))
		    this.events.remove(event);
	   }
	}
	
	public void removeEvents(Event [] events)
	{
       for(Event event : events)
    	 this.removeEvent(event);
	}
	
	public void removeEvents(String [] eventNames)
	{
       for(String eventName : eventNames)
    	 this.removeEvent(eventName);
	}
	
	// Protected members
	protected String name;
	
	// Private members
	private LinkedList<Event> events;
}

// End of File
